package cn.example.demo.modules.house.service.impl;

import cn.example.demo.common.model.service.ServiceResult;
import cn.example.demo.common.retrieval.PageBean;
import cn.example.demo.common.secure.annotation.DataScopeEnable;
import cn.example.demo.common.secure.context.LoginUserApi;
import cn.example.demo.common.tools.QueryServiceUtils;
import cn.example.demo.common.tools.obj.reflect.EntityUtils;
import cn.example.demo.modules.house.dto.UserBehaviorDto;
import cn.example.demo.modules.house.entity.UserBehavior;
import cn.example.demo.modules.house.mapper.UserBehaviorMapper;
import cn.example.demo.modules.house.recommend.BehaviorType;
import cn.example.demo.modules.house.recommend.BehaviorWeightCalculator;
import cn.example.demo.modules.house.service.IUserBehaviorService;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.NullNode;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;

/**
 * 描述：【用户行为记录】接口实现类
 */
@EnableAspectJAutoProxy(exposeProxy = true, proxyTargetClass = true)
@Service
public class UserBehaviorServiceImpl extends ServiceImpl<UserBehaviorMapper, UserBehavior> implements IUserBehaviorService {
    @Autowired
    private LoginUserApi loginUserApi;
    @Autowired
    private BehaviorWeightCalculator behaviorWeightCalculator;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ServiceResult insertUserBehavior(UserBehaviorDto userBehaviorDto) {
        UserBehavior entity = EntityUtils.entityConvert(userBehaviorDto, new UserBehavior(), false);
        // 计算权重
        entity.setWeight(behaviorWeightCalculator.calculate(BehaviorType.valueOf(userBehaviorDto.getBehaviorType()), StrUtil.isNotBlank(userBehaviorDto.getExtraInfo()) ? JSONUtil.toBean(userBehaviorDto.getExtraInfo(), JsonNode.class) : NullNode.getInstance()));
        if (entity.getUserId() == null) {
            entity.setUserId(loginUserApi.getCurrentLoginUser().getUserId());
        }
        if (this.save(entity)) {
            return ServiceResult.isSuccess(StrUtil.format("【用户行为记录，ID:{}】创建成功!", entity.getId()), entity);
        }
        return ServiceResult.isInternalError("【用户行为记录】创建失败，未知错误！");
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ServiceResult updateUserBehavior(UserBehaviorDto userBehaviorDto) {
        UserBehavior entity = this.getById(userBehaviorDto.getId());
        if (entity == null) {
            return ServiceResult.isNotFound(StrUtil.format("【用户行为记录】信息更新失败：记录不存在！ID:{}", userBehaviorDto.getId()));
        }

        entity = EntityUtils.entityConvert(userBehaviorDto, entity, true);
        if (this.updateById(entity)) {
            return ServiceResult.isSuccess(StrUtil.format("【用户行为记录，ID:{}】信息更新成功!", entity.getId()), null);
        }

        return ServiceResult.isNotModified("未知错误，【用户行为记录】信息修改失败！");
    }

    @Override
    public PageBean<UserBehavior> queryUserBehavior(UserBehaviorDto userBehaviorDto) {
        // 当前实现类代理对象
        UserBehaviorServiceImpl proxy = (UserBehaviorServiceImpl) AopContext.currentProxy();

        Page<UserBehavior> pageResult = PageHelper.startPage(userBehaviorDto.getPageNum(), userBehaviorDto.getPageSize())
                .doSelectPage(() -> this.list(proxy.getQueryWrapper(userBehaviorDto)));

        return QueryServiceUtils.encapsulatePageBean(new PageBean<>(), pageResult);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ServiceResult deleteUserBehavior(UserBehaviorDto userBehaviorDto) {
        int rows = this.baseMapper.deleteBatchIds(userBehaviorDto.getIds());
        if (rows > 0) {
            return ServiceResult.isSuccess(StrUtil.format("操作成功，已批量删除【用户行为记录】共 {} 条记录！", rows), rows);
        }

        return ServiceResult.isNotModified("删除【用户行为记录】失败，请稍后重试！");
    }

    @Override
    public UserBehavior findUserBehaviorById(String id) {
        return this.getById(id);
    }

    @Override
    public List<Map<String, Object>> queryUserBehaviorAsDict(UserBehaviorDto userBehaviorDto) {
        return this.baseMapper.selectAsDictList(getQueryWrapper(userBehaviorDto));
    }

    /**
     * 查询条件
     *
     * @param userBehaviorDto
     * @return
     */
    @DataScopeEnable
    protected LambdaQueryWrapper getQueryWrapper(UserBehaviorDto userBehaviorDto) {
        LambdaQueryWrapper<UserBehavior> wrapper = Wrappers.lambdaQuery();

        wrapper
                .eq(userBehaviorDto.getId() != null, UserBehavior::getId, userBehaviorDto.getId())

                .eq(userBehaviorDto.getUserId() != null, UserBehavior::getUserId, userBehaviorDto.getUserId())

                .like(StrUtil.isNotBlank(userBehaviorDto.getHouseId()), UserBehavior::getHouseId, userBehaviorDto.getHouseId())

                .eq(userBehaviorDto.getBehaviorType() != null, UserBehavior::getBehaviorType, userBehaviorDto.getBehaviorType())

                .eq(userBehaviorDto.getWeight() != null, UserBehavior::getWeight, userBehaviorDto.getWeight())

                .eq(userBehaviorDto.getExtraInfo() != null, UserBehavior::getExtraInfo, userBehaviorDto.getExtraInfo())

                .eq(userBehaviorDto.getOrganizationId() != null, UserBehavior::getOrganizationId, userBehaviorDto.getOrganizationId())

                .eq(userBehaviorDto.getCreateUser() != null, UserBehavior::getCreateUser, userBehaviorDto.getCreateUser())

                .like(StrUtil.isNotBlank(userBehaviorDto.getCreateUserName()), UserBehavior::getCreateUserName, userBehaviorDto.getCreateUserName())

                .ge(userBehaviorDto.getCreateTimeStart() != null, UserBehavior::getCreateTime, userBehaviorDto.getCreateTimeStart())
                .le(userBehaviorDto.getCreateTimeEnd() != null, UserBehavior::getCreateTime, userBehaviorDto.getCreateTimeEnd())

                .eq(userBehaviorDto.getUpdateUser() != null, UserBehavior::getUpdateUser, userBehaviorDto.getUpdateUser())

                .like(StrUtil.isNotBlank(userBehaviorDto.getUpdateUserName()), UserBehavior::getUpdateUserName, userBehaviorDto.getUpdateUserName())

                .ge(userBehaviorDto.getUpdateTimeStart() != null, UserBehavior::getUpdateTime, userBehaviorDto.getUpdateTimeStart())
                .le(userBehaviorDto.getUpdateTimeEnd() != null, UserBehavior::getUpdateTime, userBehaviorDto.getUpdateTimeEnd())
        ;

        return wrapper;
    }
}
